package org.dtrd.modules.patient.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Iterators;
import org.dtrd.common.exception.JeecgBootException;
import org.dtrd.common.util.CheckUtil;
import org.dtrd.common.util.DateUtils;
import org.dtrd.config.system.Constant;
import org.dtrd.config.system.Constant.BloodPressureRecordType;
import org.dtrd.config.system.Constant.RecordType;
import org.dtrd.config.system.Constant.SleepStatus;
import org.dtrd.modules.achievement.entity.bean.PatientSigninPlan;
import org.dtrd.modules.achievement.service.IDtrdEntRdSigninPlanService;
import org.dtrd.modules.achievement.service.IDtrdEntRdSigninRecordService;
import org.dtrd.modules.archive.entity.bean.report.*;
import org.dtrd.modules.archive.entity.po.*;
import org.dtrd.modules.archive.service.*;
import org.dtrd.modules.control.entity.po.DtrdEntRdSigninTargetDetail;
import org.dtrd.modules.control.service.IDtrdEntRdSigninTargetDetailService;
import org.dtrd.modules.dict.service.IDtrdEntRdDicDistrictService;
import org.dtrd.modules.evaluation.entity.bean.report.TotalEvaluationReports;
import org.dtrd.modules.evaluation.service.IDtrdEntRdEvaluationService;
import org.dtrd.modules.patient.entity.bean.report.*;
import org.dtrd.modules.patient.entity.po.DtrdEntRdPatient;
import org.dtrd.modules.patient.entity.po.DtrdEntRdReport;
import org.dtrd.modules.patient.entity.po.DtrdEntRdReportTarget;
import org.dtrd.modules.patient.mapper.DtrdEntRdReportMapper;
import org.dtrd.modules.archive.service.IDtrdEntRdArchiveBasicFamilyService;
import org.dtrd.modules.archive.service.IDtrdEntRdArchiveBasicService;
import org.dtrd.modules.patient.service.IDtrdEntRdPatientService;
import org.dtrd.modules.patient.service.IDtrdEntRdReportService;
import org.dtrd.modules.patient.service.IDtrdEntRdReportTargetService;
import org.dtrd.modules.record.entity.bean.PeriodBloodPressure;
import org.dtrd.modules.record.entity.bean.PeriodBmi;
import org.dtrd.modules.record.entity.bean.SigninSuggestBean;
import org.dtrd.modules.record.entity.bean.SugarChart;
import org.dtrd.modules.record.entity.po.DtrdEntRdSigninBody;
import org.dtrd.modules.record.entity.po.DtrdEntRdSigninSuggest;
import org.dtrd.modules.record.entity.po.DtrdViewRlCheckinRecord;
import org.dtrd.modules.record.service.*;
import org.dtrd.modules.record.mapper.DtrdEntRdBloodPressureMapper;
import org.dtrd.modules.record.mapper.DtrdEntRdHeightWeightMapper;
import org.dtrd.modules.record.service.*;
import org.dtrd.modules.service.entity.po.DtrdRlPackagePatient;
import org.dtrd.modules.service.entity.po.DtrdRlPatientServiceDetail;
import org.dtrd.modules.service.service.IDtrdEntRdServicePackageService;
import org.dtrd.modules.service.service.IDtrdRlPackagePatientService;
import org.dtrd.modules.suggest.entity.bean.PeriodFoodScore;
import org.dtrd.modules.suggest.service.IDtrdEntRdSigninRecordSuggestService;
import org.dtrd.modules.suggest.service.IDtrdEntRdSigninRecordSuggestService;
import org.dtrd.modules.system.service.ISysUserService;
import org.dtrd.modules.util.ReportUtil;
import org.dtrd.modules.util.SchemeUtil;
import org.dtrd.modules.util.SigninUtil;
import org.dtrd.common.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 患者报告 服务实现类
 * </p>
 *
 * @author QR
 * @since 2022-01-22
 */
@DS("multi-datasource1")
@Service
@Slf4j
public class DtrdEntRdReportServiceImpl extends ServiceImpl<DtrdEntRdReportMapper, DtrdEntRdReport> implements IDtrdEntRdReportService {

    @Autowired
    private IDtrdEntRdArchiveBasicService basicService;
    @Autowired
    private IDtrdEntRdArchiveBasicFamilyService basicFamilyService;
    @Autowired
    private IDtrdEntRdDicDistrictService districtInfoService;
    @Autowired
    private IDtrdEntRdComorbidityService comorbidityService;
    @Autowired
    private IDtrdEntRdComplicationService complicationService;
    @Autowired
    private IDtrdEntRdEducationService educationService;
    @Autowired
    private IDtrdEntRdOverviewService overviewService;
    @Autowired
    private IDtrdEntRdLifewayService lifewayService;
    @Autowired
    private IDtrdEntRdAnamnesisService anamnesisService;
    @Autowired
    private IDtrdEntRdEvaluationService evaluationService;
    @Autowired
    private IDtrdEntRdIconographyService iconographyService;
    @Autowired
    private IDtrdEntRdLaboratoryService laboratoryService;
    @Autowired
    private IDtrdEntRdArchiveReverseSchemeService reverseSchemeService;
    @Autowired
    private IDtrdEntRdPhysicalService physicalService;
    @Autowired
    private IDtrdEntRdPatientService patientService;
    @Autowired
    private IDtrdEntRdServicePackageService packageService;
    @Autowired
    private IDtrdRlPackagePatientService packagePatientRlService;
    @Autowired
    private IDtrdEntRdSigninTargetDetailService targetDetailService;
    @Autowired
    private IDtrdEntRdSigninSuggestService suggestService;
    @Autowired
    private IDtrdEntRdSigninRecordService signinRecordService;
    @Autowired
    private IDtrdViewRlCheckinRecordService checkinRecordService;
    @Autowired
    private IDtrdEntRdUplowRecordService uplowRecordService;
    @Autowired
    private IDtrdEntRdSigninPlanService signinPlanService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISugarRecordService sugarRecordService;
    @Autowired
    private IBloodPressureRecordService bloodPressureRecordService;
    @Autowired
    private IHeightWeightRecordService heightWeightRecordService;
    @Autowired
    private IDtrdEntRdSigninRecordSuggestService signinRecordSuggestService;
    @Autowired
    private IDtrdEntRdSigninTargetDetailService signinTargetDetailService;
    @Autowired
    private IDtrdEntRdSigninBodyService signinBodyService;
    @Autowired
    private IDtrdEntRdReportTargetService reportTargetService;
    @Autowired
    private IDtrdEntRdArchiveReportService archiveReportService;

    @Override
    public boolean isValidReportId(Integer reportId) {
        DtrdEntRdReport report = getById(reportId);
        return Optional.ofNullable(report).isPresent();
    }

    @Override
    public ReportFirst createReportFirst(Integer patientId, String username) {
        ReportFirst report = new ReportFirst(patientId);
        // 获取档案内容
        PatientArchive archive = getReportPatientArchive(patientId, true, true, true, true);
        // 量表评估
        TotalEvaluationReports totalEvaluationReports = evaluationService.getTotalEvaluationReports(patientId, new Date());
        // 服务方案
        PatientServiceProgramme serviceProgramme = reverseSchemeService.getPatientServiceProgramme(patientId);
        // 设置返回结果
        report.setPatientArchive(archive);
        report.setPatientEvaluation(totalEvaluationReports);
        report.setPatientServiceProgramme(serviceProgramme);
        // 保存记录/设置报告名字
        DtrdEntRdReport po = new DtrdEntRdReport().parseFromDTO(report);
        po.setReportType(Constant.ReportType.REPORT_FIRST.getType());
        String packageName = packageService.getServingPackageName(patientId);
        po.setReportName(packageName + Constant.ReportType.REPORT_FIRST.getName());
        po.setCreateBy(username);
        save(po);
        return report;
    }

    @Override
    public ReportFirst createReportFirstV2(Integer patientId, String username)
    {
        ReportFirst report = new ReportFirst(patientId);// 获取档案内容
        PatientArchive archive = getReportPatientArchive(patientId, true, false, true, true);
        // 量表评估
        TotalEvaluationReports totalEvaluationReports = evaluationService.getTotalEvaluationReports(patientId, new Date());
        // 服务方案
        PatientServiceProgramme serviceProgramme = reverseSchemeService.getPatientServiceProgramme(patientId);
        // 报告单: 日常监测-人体成分分析、患者档案-体格检查、实验室检测、影像学检测
//        String archiveReport = getPatientArchiveUploadedReport(patientId);
        String archiveReport = getAllArchiveReportPhotos(patientId);
        // 设置返回结果
        report.setPatientArchive(archive);
        report.setPatientEvaluation(totalEvaluationReports);
        report.setPatientServiceProgramme(serviceProgramme);
        report.setPatientArchiveReport(archiveReport);
        report.setFirstEvaluate(new ReportFirstUpdateRequest().init());
        // 保存记录/设置报告名字
        DtrdEntRdReport po = new DtrdEntRdReport().parseFromDTO(report);
        po.setReportType(Constant.ReportType.REPORT_FIRST.getType());
        DtrdEntRdPatient patient = patientService.getById(patientId);
        po.setReportName(patient.getPatientsName() + Constant.ReportType.REPORT_FIRST.getName());
        po.setCreateBy(username);
        save(po);
        return null;
    }

    private String getAllArchiveReportPhotos(Integer patientId){
        StringBuilder result = new StringBuilder();
        LambdaQueryWrapper<DtrdEntRdArchiveReport> queryWrapper = Wrappers.lambdaQuery(DtrdEntRdArchiveReport.class)
                .eq(DtrdEntRdArchiveReport::getIsDel, 0)
                .eq(DtrdEntRdArchiveReport::getPatientId, patientId);
        List<DtrdEntRdArchiveReport> list = archiveReportService.list(queryWrapper);
        if(CollectionUtil.isEmpty(list)){
            return null;
        }
        for(DtrdEntRdArchiveReport archiveReport: list){
            if(StrUtil.isBlank(archiveReport.getReportUrls())){
                continue;
            }
            result.append(archiveReport.getReportUrls());
            result.append(",");
        }
        return result.length() > 1 ? result.substring(0, result.length()-1) : result.toString();
    }

    @Override
    public String getPatientArchiveUploadedReport(Integer patientId) {
        PatientArchiveReport archiveReport = new PatientArchiveReport();
        // 日常监测-人体成分分析、dtrd_ent_rd_signin_body

        // 患者档案-体格检查、dtrd_ent_rd_archive_physical
        DtrdEntRdArchivePhysical physicalReport = physicalService.getPatientPhysical(patientId);
        log.info("physicalReport=====" + JSONUtil.toJsonStr(physicalReport));
        if (physicalReport != null) {
            archiveReport.setPhysicalBasicReport(physicalReport.getBasicReportPhoto());
            archiveReport.setPhysicalSkinReport(physicalReport.getSkinReportPhoto());
            archiveReport.setPhysicalFootReport(physicalReport.getFootReportPhoto());
            archiveReport.setPhysicalEyeReport(physicalReport.getEyeReportPhoto());
            archiveReport.setPhysicalOtherReport(physicalReport.getOtherReportPhoto());
        }
        // 患者档案-实验室检测、dtrd_ent_rd_archive_laboratory
        DtrdEntRdArchiveLaboratory laboratoryReport = laboratoryService.getPatientLaboratory(patientId);
        log.info("laboratoryReport=====" + JSONUtil.toJsonStr(laboratoryReport));
        if (laboratoryReport != null) {
            archiveReport.setLaboratorySugarReport(laboratoryReport.getSugarReportPhoto());
            archiveReport.setLaboratoryBloodReport(laboratoryReport.getBloodReportPhoto());
            archiveReport.setLaboratoryKetoneReport(laboratoryReport.getKetoneReportPhoto());
            archiveReport.setLaboratoryKidneyReport(laboratoryReport.getKidneyReportPhoto());
            archiveReport.setLaboratoryLipidReport(laboratoryReport.getLiverReportPhoto());
            archiveReport.setLaboratoryLiverReport(laboratoryReport.getLiverReportPhoto());
            archiveReport.setLaboratoryOggtReport(laboratoryReport.getOgttReportPhoto());
        }
        // 患者档案-影像学检测 dtrd_ent_rd_archive_iconography
        IconographyReport iconographyReport = iconographyService.getPatientIconographyReport(patientId);
        if (iconographyReport != null) {
            archiveReport.setIconographyReport(iconographyReport.getPhoto());
        }

        String archiveReportJson = JSONUtil.toJsonStr(archiveReport);
        StringBuilder img = new StringBuilder();
        JSONObject archiveReportObject = JSONUtil.parseObj(archiveReportJson);
        for (Map.Entry<String, Object> entry : archiveReportObject.entrySet()) {
            String s = entry.getKey();
            img.append(archiveReportObject.get(s)).append(",");
        }

        String data = img.toString();
        if (!data.equals("")) {
            data = data.substring(0, data.length()-1);
        }
        return data;
    }

    @Override
    public ReportWeek createReportWeek(Integer patientId, String reportName) {
        ReportWeek reportWeek = new ReportWeek();
        // 获取当前的时间,获取上周的起始时间和结束时间
        Date startTime = DateUtils.getLastWeekMonday();
        Date endTime = DateUtils.getLastWeekSunday();
        Date lastStartTime = DateUtil.beginOfWeek(DateUtil.offset(startTime,DateField.DAY_OF_WEEK, -7));
        Date lastEndTime = DateUtil.endOfWeek(DateUtil.offset(startTime, DateField.DAY_OF_WEEK, -7));
        System.out.println("起始时间为：" + startTime + " 结束时间为：" + endTime);
        ReportWeek.WeekReportContent content = new ReportWeek.WeekReportContent();
        // region 基本信息
        PatientBasicInfo basicInfo = getPatientBasicInfo(patientId);
        content.setBasicInfo(basicInfo);
        // endregion
        // region 服务方案
        ReportServiceProgramme serviceProgramme = getPatientServiceProgramme(patientId);
        Optional.ofNullable(serviceProgramme).ifPresent(content::setServiceProgramme);
        String startDate = null,endDate = null;
        String lastStartDate = null, lastEndDate = null;
        if (serviceProgramme != null) {
            startDate = DateUtils.compareYMD(serviceProgramme.getStartDate(),startTime)? serviceProgramme.getServiceStartDate():DateUtil.formatDate(startTime);
            lastStartDate = DateUtils.compareYMD(serviceProgramme.getStartDate(),lastStartTime)? serviceProgramme.getServiceStartDate():DateUtil.formatDate(lastStartTime);
            endDate = DateUtils.compareYMD(serviceProgramme.getEndDate(),endTime)?DateUtil.formatDate(endTime):serviceProgramme.getServiceFinishDate();
            lastEndDate = DateUtils.compareYMD(serviceProgramme.getEndDate(),lastEndTime)?DateUtil.formatDate(lastEndTime):serviceProgramme.getServiceFinishDate();
        }else {
            startDate = DateUtil.formatDate(startTime);
            lastStartDate = DateUtil.formatDate(lastStartTime);
            endDate = DateUtil.formatDate(endTime);
            lastEndDate = DateUtil.formatDate(lastEndTime);
        }
        lastStartTime = DateUtils.str2Date(lastStartDate, DateUtils.date_sdf.get());
        lastEndTime = DateUtils.str2Date(lastEndDate, DateUtils.date_sdf.get());
        // endregion
        // region 打卡计划
        ReportTable reportTable = handleSigninRecords(patientId);
        if (reportTable != null) {
            content.setDailySigninRecords(reportTable);
            content.setWeeklySigninRate(reportTable.getExtraData1());
        }
        // endregion

        // region 控制目标 该方法已弃用，控制目标图表的生成已替换为setControllerTargetReportList
//        content.setTargets(targetDetailService.getReportWeekTargets(patientId, startDate, endDate));
        // endregion

        // region建议内容
        ReportWeekSuggest patientSuggest = getPatientSuggest(patientId);
        // 计算周期内饮食打卡每餐平均得分
        Float dietScore = signinRecordSuggestService.getPatientSigninDietRecordScoreAvg(patientId, startDate, endDate);
        if( dietScore != null){
            if(patientSuggest == null){
                patientSuggest = new ReportWeekSuggest();
            }
            dietScore = (float)Math.round(dietScore*100)/100;
            patientSuggest.setDietScore(dietScore);
        }
        content.setSuggests(patientSuggest);
        // endregion
        // region 日常监测趋势血糖模块（空腹与餐后血糖）
        int sourceType = 0; // 代表查询全部仪器的血糖
        content.setSugarChart(sugarRecordService.getBloodSugarRecordsForCharts(patientId, startDate, endDate, sourceType));
        // endregion
        // region 日常监测趋势血压模块
        content.setPeriodBloodPressure(bloodPressureRecordService.getBloodPressureRecordsForCharts(patientId, startDate, endDate));
        // endregion
        // region 日常监测趋势体重模块 周报不需要，体重分析从人体成分分析中获取
//        content.setPeriodBmi(heightWeightRecordService.getBmiDataForCharts(patientId, startDate, endDate));
        // endregion
        // region 控制目标周期查询图表
        content.setControllerTargetReportList(signinTargetDetailService.getPeriodReportTarget(patientId, startDate, endDate, lastStartDate, lastEndDate,
                DateUtils.compareYMD(lastEndTime, lastStartTime), Constant.ReportType.REPORT_WEEK));
        reportWeek.setReportContent(content);
        // endregion
        // region 获取周报人体报告单的报告
        String reportPicture = getBodyPicture(patientId, startDate, endDate);
        reportWeek.weekInputUpdate.setReportPictures(reportPicture);
        // endregion 获取周报人体报告单的报告
        // region保存
        DtrdEntRdReport po = new DtrdEntRdReport().init();
        po.setReportName(reportName);
        po.setReportType(Constant.ReportType.REPORT_WEEK.getType());
        po.setPatientId(patientId);
        po.setPatientArchive(JSONUtil.toJsonStr(content));
        po.setPatientArchiveReport(JSONUtil.toJsonStr(reportWeek.weekInputUpdate));
        po.setCreateBy(po.getCreateBy());
        save(po);
        // endregion
        return reportWeek.parseFromPO(po);
    }

    private String getBodyPicture(Integer patientId, String startDate, String endDate){
        StringBuilder result = new StringBuilder();
        LambdaQueryWrapper<DtrdEntRdSigninBody> queryWrapper = Wrappers.lambdaQuery(DtrdEntRdSigninBody.class)
                .eq(DtrdEntRdSigninBody::getIsDel, 0)
                .eq(DtrdEntRdSigninBody::getPatientId, patientId)
                .ge(DtrdEntRdSigninBody::getRecordDate, startDate)
                .le(DtrdEntRdSigninBody::getRecordDate, endDate);
        List<DtrdEntRdSigninBody> list = signinBodyService.list(queryWrapper);
        if(CollectionUtil.isEmpty(list)){
            return null;
        }
        for(DtrdEntRdSigninBody temp : list){
            if(StrUtil.isBlank(temp.getRecordPhoto())){
                continue;
            }
            result.append(temp.getRecordPhoto());
            result.append(",");
        }
        return result.length() > 1 ? result.substring(0, result.length()-1) : result.toString();
    }

    @Override
    public ReportMonth createReportMonth(Integer patientId, String reportName) {
        ReportMonth reportMonth = new ReportMonth();
        // 获取当前的时间,获取上月的起始时间和结束时间
        Date startTime = DateUtils.getLastMonthFirst();
        Date endTime = DateUtils.getLastMonthEnd();
        // 获取上上个月的起始结束时间
        Date lastStartTime = DateUtil.beginOfMonth(DateUtil.offset(startTime, DateField.DAY_OF_MONTH, -28));
        Date lastEndTime = DateUtil.endOfMonth(DateUtil.offset(startTime, DateField.DAY_OF_MONTH, -28));
        System.out.println("起始时间为：" + startTime + " 结束时间为：" + endTime);
        ReportMonth.MonthReportContent content = new ReportMonth.MonthReportContent();
        // region 基本信息
        PatientBasicInfo basicInfo = getPatientBasicInfo(patientId);
        content.setBasicInfo(basicInfo);
        // endregion
        // region 服务方案
        ReportServiceProgramme serviceProgramme = getPatientServiceProgramme(patientId);
        Optional.ofNullable(serviceProgramme).ifPresent(content::setServiceProgramme);
        String startDate = null,endDate = null;
        String lastStartDate = null, lastEndDate = null;
        if (serviceProgramme != null) {
            startDate = DateUtils.compareYMD(serviceProgramme.getStartDate(),startTime)? serviceProgramme.getServiceStartDate():DateUtil.formatDate(startTime);
            lastStartDate = DateUtils.compareYMD(serviceProgramme.getStartDate(),lastStartTime)? serviceProgramme.getServiceStartDate():DateUtil.formatDate(lastStartTime);
            endDate = DateUtils.compareYMD(serviceProgramme.getEndDate(),endTime)?DateUtil.formatDate(endTime):serviceProgramme.getServiceFinishDate();
            lastEndDate = DateUtils.compareYMD(serviceProgramme.getEndDate(),lastEndTime)?DateUtil.formatDate(lastEndTime):serviceProgramme.getServiceFinishDate();
        }else {
            startDate = DateUtil.formatDate(startTime);
            lastStartDate = DateUtil.formatDate(lastStartTime);
            endDate = DateUtil.formatDate(endTime);
            lastEndDate = DateUtil.formatDate(lastEndTime);
        }
        lastStartTime = DateUtils.str2Date(lastStartDate, DateUtils.date_sdf.get());
        lastEndTime = DateUtils.str2Date(lastEndDate, DateUtils.date_sdf.get());
        // endregion
        // region 打卡计划
        ReportTable reportTable = handleSigninRecords(patientId);
        if (reportTable != null) {
            content.setDailySigninRecords(reportTable);
            content.setWeeklySigninRate(reportTable.getExtraData1());
        }
        // endregion
        // region 打卡率和达标率计算
        Date startDTemp = DateUtils.str2Date(startDate,DateUtils.date_sdf.get());
        Date endDTemp = DateUtils.str2Date(endDate, DateUtils.date_sdf.get());
        Map<Date, Integer> finishedRateMap = signinRecordService.getSigninFinishedRateMap(patientId, startDTemp, endDTemp);
//        Map<Date, Integer> reachStandardMap = uplowRecordService.getSugarReachStandard(patientId, startDTemp, endDTemp);
        Map<Integer, DtrdEntRdSigninTargetDetail> detailMap = getSigninTargetDetail(patientId, startDTemp, endDTemp);
        Map<Date, Integer> reachStandardMap = null;
        if(detailMap != null){
            reachStandardMap = uplowRecordService.getPeriodControllerTargetsReachRate(patientId, startDTemp, endDTemp, detailMap);
        }
        finishedRateMap = finishedRateMap==null?new HashMap<Date, Integer>():finishedRateMap;
        reachStandardMap = reachStandardMap==null?new HashMap<Date, Integer>():reachStandardMap;
        content.setSigninRateLine(ReportUtil.getFinishedAndReachStandardRate(startDTemp, endDTemp, finishedRateMap, reachStandardMap));
        // endregion

        // region 控制目标 该方法已弃用，控制目标图表的生成已替换为setControllerTargetReportList
//        content.setTargets(targetDetailService.getReportWeekTargets(patientId, startDate, endDate));
        // endregion

        // region建议内容
        ReportWeekSuggest patientSuggest = getPatientSuggest(patientId);
        // 计算周期内饮食打卡每餐平均得分
        Float dietScore = signinRecordSuggestService.getPatientSigninDietRecordScoreAvg(patientId, startDate, endDate);
        if( dietScore != null){
            if(patientSuggest == null){
                patientSuggest = new ReportWeekSuggest();
            }
            dietScore = (float)Math.round(dietScore*100)/100;
            patientSuggest.setDietScore(dietScore);
        }
        content.setSuggests(patientSuggest);
        // endregion
        // region 日常监测趋势血糖模块（空腹与餐后血糖）
        int sourceType = 0; // 代表查询全部仪器的血糖
        content.setSugarChart(sugarRecordService.getBloodSugarRecordsForCharts(patientId, startDate, endDate, sourceType));
        // endregion
        // region 日常监测趋势血压模块
        content.setPeriodBloodPressure(bloodPressureRecordService.getBloodPressureRecordsForCharts(patientId, startDate, endDate));
        // endregion
        // region 日常监测趋势体重模块， 修改为人体成分分析的数据
//        content.setPeriodBmi(heightWeightRecordService.getBmiDataForCharts(patientId, startDate, endDate));
        content.setPeriodBmi(signinBodyService.getPeriodBmiSigninBody(patientId,startDate,endDate));
        // endregion
        // region 控制目标周期查询图表
        content.setControllerTargetReportList(signinTargetDetailService.getPeriodReportTarget(patientId, startDate, endDate, lastStartDate, lastEndDate,
                DateUtils.compareYMD(lastEndTime, lastStartTime), Constant.ReportType.REPORT_MONTH));

        reportMonth.setReportContent(content);
        // endregion
        // region保存
        DtrdEntRdReport po = new DtrdEntRdReport().init();
        po.setReportName(reportName);
        po.setReportType(Constant.ReportType.REPORT_MONTH.getType());
        po.setPatientId(patientId);
        po.setPatientArchive(JSONUtil.toJsonStr(content));
        po.setCreateBy(po.getCreateBy());
        save(po);
        // endregion
        return reportMonth.parseFromPo(po);
    }

    private Map<Integer, DtrdEntRdSigninTargetDetail> getSigninTargetDetail(Integer patientId, Date startTime, Date endTime){
        List<Date> dates = new ArrayList<>(2);
        dates.add(startTime);
        dates.add(endTime);
        List<List<Date>> dateList = new ArrayList<>(1);
        dateList.add(dates);
        List<Map<Integer, DtrdEntRdSigninTargetDetail>> maps = signinTargetDetailService.getWeekSigninTargetDetail(patientId, dateList);
        return CollectionUtil.isEmpty(maps) ? null:maps.get(0);
    }

    /**
     * 获取患者周报打卡 table
     */
    private ReportTable handleSigninRecords(int patientId) {
        DateTime dateTime = DateUtil.lastWeek();
        Date time = DateUtil.beginOfWeek(dateTime.toCalendar()).getTime();
        String lastWeekStart = DateUtil.formatDate(time);
        Date time1 = DateUtil.endOfWeek(dateTime.toCalendar()).getTime();
        String lasTWeekEnd = DateUtil.formatDate(time1);
        // 打卡记录
        List<DtrdViewRlCheckinRecord> recordList = checkinRecordService.selectCheckinRecordsByRecordTypes(patientId, lastWeekStart, lasTWeekEnd, null);
        // 打卡率
        Map<String, String> dateMap = getDateToSigninRate(patientId, time, time1);
        // 没有打卡记录活打卡率直接返回空
        if (CollectionUtil.isEmpty(recordList) || MapUtil.isEmpty(dateMap)) {
            return null;
        }
        ReportTable signinRecords = new ReportTable();
        // 表头
        List<ReportTableHeader> header = new ArrayList<>(8);
        // 第一列
        header.add(new ReportTableHeader("打卡项目/时间", "k0"));
        // 每日打卡率
        Map<String, String> scoreRecord = new HashMap<>();
        MapUtil.isNotEmpty(dateMap);
        String avgRate = dateMap.get("avg");
        signinRecords.setExtraData1(avgRate);
        scoreRecord.put("k0", "打卡率");
        // 生成头部与计算每日打卡率
        // 此处依据上文 限定查询时限一周  肖 2022-04-05 21:04:35
        handleHeaderAndDailyScore(patientId, header, scoreRecord, dateMap, lastWeekStart);
        handleHeaderAndDailyScore(patientId, header, scoreRecord, dateMap, DateUtils.dateAdd(1, lastWeekStart));
        handleHeaderAndDailyScore(patientId, header, scoreRecord, dateMap, DateUtils.dateAdd(2, lastWeekStart));
        handleHeaderAndDailyScore(patientId, header, scoreRecord, dateMap, DateUtils.dateAdd(3, lastWeekStart));
        handleHeaderAndDailyScore(patientId, header, scoreRecord, dateMap, DateUtils.dateAdd(4, lastWeekStart));
        handleHeaderAndDailyScore(patientId, header, scoreRecord, dateMap, DateUtils.dateAdd(5, lastWeekStart));
        handleHeaderAndDailyScore(patientId, header, scoreRecord, dateMap, lasTWeekEnd);
        signinRecords.setHeader(header);
        if (CheckUtil.isNotEmpty(recordList)) {
            List<Map<String, String>> contentList = new ArrayList<>(8);
            contentList.add(scoreRecord);
            Map<Integer, Map<String, String>> map = new HashMap<>(20);
            // 处理数据部分
            recordList.forEach(po -> {
                String recordDate = DateUtil.formatDate(po.getRecordDate());
                String key = dateMap.get(recordDate);
                String keyValue = null, keyDescribe = null;
                RecordType recordType = RecordType.valueOf(po.getRecordType());
                if (recordType != null) {
                    if (recordType == RecordType.BLOOD_PRESSURE) {
                        // 收缩、舒张、心率
                        String signinName1 = null, signinName2 = null, signinName3 = null;
                        int subType1 = 1, subType2 = 2, subType3 = 3;
                        if (po.getSubType() == BloodPressureRecordType.MORNING.getType()) {
                            signinName1 = "晨起收缩压";
                            signinName2 = "晨起舒张压";
                            signinName3 = "晨起心率";
                        } else if (po.getSubType() == BloodPressureRecordType.EVENING.getType()) {
                            signinName1 = "睡前收缩压";
                            signinName2 = "睡前舒张压";
                            signinName3 = "睡前心率";
                            subType1 = 4;
                            subType2 = 5;
                            subType3 = 6;
                        }
                        // 收缩压
                        groupByRecordType(map, po.getRecordType() * 10 + subType1, signinName1, key, po.getRecordValue(), null);
                        // 舒张压
                        groupByRecordType(map, po.getRecordType() * 10 + subType2, signinName2, key, po.getRecordValue2(), null);
                        // 心率
                        groupByRecordType(map, po.getRecordType() * 10 + subType3, signinName3, key, po.getRecordValue3(), null);
                    } else {
                        switch (recordType) {
                            case SUGAR:
                            case WEIGHT:
                            case WAIST:
                            case INSULIN:
                            case KETONE:
                                keyValue = po.getRecordValue();
                                break;
                            case DIET:
                            case SPORT:
                            case MEDICAL:
                                keyValue = po.getRecordPhoto();
                                keyDescribe = po.getRecordValue();
                                break;
                            case SLEEP:
                                SleepStatus status = SleepStatus.valueOf(StringUtil.StrTrimInt(po.getRecordValue()));
                                if (status != null) {
                                    keyValue = status.getSleepStatusDesc();
                                }
                                break;
                            default:
                                break;
                        }
                        groupByRecordType(map, po.getRecordType() * 10 + po.getSubType(), SigninUtil.getSigninName(po.getRecordType(), po.getSubType()), key, keyValue, keyDescribe);
                    }
                }
            });
            log.info("DtrdEntRdReportServiceImpl.handleSigninRecords.[patientId] " + map);
            map.keySet().stream().sorted(Comparator.comparingInt(o -> o)).map(map::get).peek(recordMap -> dateMap.values().forEach(key -> {
                if (!recordMap.containsKey(key)) {
                    recordMap.put(key, "");
                }
                recordMap.remove(avgRate);
            })).forEach(contentList::add);
            signinRecords.setContent(contentList);

        }
        return signinRecords;
    }

    /**
     * 获取总结报告 table
     */
    private ReportTable handleSummarySigninRecords(int patientId, Date startDate, Date endDate) {
        ReportTable signinRecords = new ReportTable();
        // 每周的打卡率，没有打卡率说明没有 signin_record 的记录
        Map<String, String> weekToKey = signinRecordService.getSigninFinishedRateWeeklyMap(patientId, startDate, endDate);
        if (MapUtil.isEmpty(weekToKey)) {
            return null;
        }
        //region表头
        // 生成头部与计算每日打卡率
        List<String> weeks = DateUtils.weeks(startDate, endDate);
        List<ReportTableHeader> header = new ArrayList<>(weeks.size()+1);
        // 第一列
        header.add(new ReportTableHeader("打卡项目/时间", "k0"));
        // 每日打卡率
        Map<String, String> scoreRecord = new HashMap<>();
        scoreRecord.put("k0", "打卡率");
        for (int i = 0; i < weeks.size(); i++) {
            handleHeaderAndDailyScoreSummary(header, scoreRecord, weekToKey, i, weeks.get(i));
        }
        signinRecords.setHeader(header);
        //endregion
        //region 表格数据
        List<Map<String, String>> contentList = new ArrayList<>(weeks.size()+1);
        contentList.add(scoreRecord);
        // 打卡数据
        List<DtrdViewRlCheckinRecord> recordList = checkinRecordService.selectCheckinGroupRecordsByRecordTypes(patientId, DateUtil.formatDate(startDate), DateUtil.formatDate(endDate), null);
        if (CheckUtil.isNotEmpty(recordList)) {
            Map<Integer, Map<String, String>> map = new HashMap<>(20);
            // 打卡数据
            recordList.forEach(po -> {
                String week = po.getWeek();
                String key = weekToKey.get(week);
                String keyValue = null;
                RecordType recordType = RecordType.valueOf(po.getRecordType());
                if (recordType != null) {
                    if (recordType == RecordType.BLOOD_PRESSURE) {
                        // 收缩、舒张、心率
                        String signinName1 = null, signinName2 = null, signinName3 = null;
                        int subType1 = 1, subType2 = 2, subType3 = 3;
                        if (po.getSubType() == BloodPressureRecordType.MORNING.getType()) {
                            signinName1 = "晨起收缩压";
                            signinName2 = "晨起舒张压";
                            signinName3 = "晨起心率";
                        } else if (po.getSubType() == BloodPressureRecordType.EVENING.getType()) {
                            signinName1 = "睡前收缩压";
                            signinName2 = "睡前舒张压";
                            signinName3 = "睡前心率";
                            subType1 = 4;
                            subType2 = 5;
                            subType3 = 6;
                        }
                        // 收缩压
                        groupByRecordType(map, po.getRecordType() * 10 + subType1, signinName1, key, po.getRecordValue(), null);
                        // 舒张压
                        groupByRecordType(map, po.getRecordType() * 10 + subType2, signinName2, key, po.getRecordValue2(), null);
                        // 心率
                        groupByRecordType(map, po.getRecordType() * 10 + subType3, signinName3, key, po.getRecordValue3(), null);
                    } else {
                        switch (recordType) {
                            case SUGAR:
                            case WEIGHT:
                            case WAIST:
                            case KETONE:
                                keyValue = po.getRecordValue();
                                break;
                            case SLEEP:
                                SleepStatus status = SleepStatus.valueOf(StringUtil.StrTrimInt(po.getRecordValue()));
                                if (status != null) {
                                    keyValue = status.getSleepStatusDesc();
                                }
                                break;
                            default:
                                break;
                        }
                        groupByRecordType(map, po.getRecordType() * 10 + po.getSubType(), SigninUtil.getSigninName(po.getRecordType(), po.getSubType()), key, keyValue, null);
                    }
                }
            });
            map.keySet().stream().sorted(Comparator.comparingInt(o -> o)).map(map::get).peek(recordMap -> weekToKey.values().forEach(key -> {
                if (!recordMap.containsKey(key)) {
                    recordMap.put(key, "");
                }
            })).forEach(contentList::add);
        }
        // 建议数据
        Map<String, List<DtrdEntRdSigninSuggest>> dateToSuggests = suggestService.getWeeklySuggestMap(patientId, startDate, endDate,
                Constant.SuggestType.DIET.getType(),
                Constant.SuggestType.MEDICAL.getType(),
                Constant.SuggestType.SPORT.getType(),
                Constant.SuggestType.INSULIN.getType());
        if (MapUtil.isNotEmpty(dateToSuggests)) {
            Map<Integer, Map<String, String>> typeToMap = new HashMap<>(4);
            for (Map.Entry<String, List<DtrdEntRdSigninSuggest>> entry : dateToSuggests.entrySet()) {
                String key = weekToKey.get(entry.getKey());
                List<DtrdEntRdSigninSuggest> suggests = entry.getValue();
                for (DtrdEntRdSigninSuggest suggest : suggests) {
                    Integer signinType = suggest.getSigninType();
                    Map<String, String> map = typeToMap.get(signinType);
                    if (MapUtil.isEmpty(map)) {
                        map = new HashMap<>();
                        map.put("k0", Constant.SuggestType.valueOf(signinType).getName() + "建议");
                        typeToMap.put(signinType, map);
                    }
                    map.put(key, suggest.getSuggestContent());
                }
            }
            // 补上空值
            typeToMap.keySet().stream()
                    .sorted(Comparator.comparingInt(o -> o))
                    .map(typeToMap::get)
                    .peek(recordMap -> weekToKey.values().forEach(key -> {
                        if (!recordMap.containsKey(key)) {
                            recordMap.put(key, "");
                        }
            })).forEach(contentList::add);
        }
        signinRecords.setContent(contentList);
        //endregion
        return signinRecords;
    }


    private void groupByRecordType(Map<Integer, Map<String, String>> map, Integer mapIndex, String signinName, String key, String keyValue, String keyDescribe) {
        Map<String, String> tmp = map.get(mapIndex);
        if (tmp == null) {
            tmp = new HashMap<>(8);
        }
        tmp.put("k0", signinName);
        if (keyValue != null) {
            tmp.put(key, keyValue);
        }
        if (keyDescribe != null) {
            tmp.put(key + "Describe", keyDescribe);
        }
        map.put(mapIndex, tmp);
    }

    /**
     * 生成表头，并查询处理每日打卡
     */
    private void handleHeaderAndDailyScore(int patientId, List<ReportTableHeader> header, Map<String, String> scoreRecord, Map<String, String> dateMap, String date) {
        header.add(new ReportTableHeader(date, "k" + header.size()));
        //region 处理每日打卡率
        // 获取打卡率
        String value = dateMap.get(date);
        String key = "k" + scoreRecord.size();
        scoreRecord.put(key, value);
        // 记录日期与key的对应关系
        dateMap.put(date, key);
        //endregion
    }

    /**
     * 生成总结报告打卡总结表头
     */
    private void handleHeaderAndDailyScoreSummary(List<ReportTableHeader> header, Map<String, String> scoreRecord, Map<String, String> dateMap, Integer index, String week) {
        String name = "第" + (index+1) + "周";
        header.add(new ReportTableHeader(name, "k" + header.size()));
        //region 处理每日打卡率
        String key = "k" + scoreRecord.size();
        scoreRecord.put(key, dateMap.getOrDefault(week, "0%"));
        // 记录日期与key的对应关系
        dateMap.put(week, key);
        //endregion
    }

    private Map<String, String> getDateToSigninRate(Integer patientId, Date start, Date endDate) {
        Map<Date, Integer> map = signinRecordService.getSigninFinishedRateMap(patientId, start, endDate);
        if (MapUtil.isNotEmpty(map)) {
            Map<String, String> newMap = new HashMap<>(map.size());
            if (CollectionUtil.isNotEmpty(map)) {
                Integer rateSum = 0;
                for (Map.Entry<Date, Integer> entry : map.entrySet()) {
                    Integer rate = entry.getValue();
                    newMap.put(DateUtil.formatDate(entry.getKey()), rate+"%");
                    rateSum += rate;
                }
                int avgRate = rateSum / map.size();
                newMap.put("avg", avgRate+"%");
            }
            return newMap;
        }
        return null;
    }

    @Override
    public ReportSummary createReportSummary(Integer patientId, String username) {
        ReportSummary reportSummary = new ReportSummary();
        // region获取首诊报告
        ReportFirst firstReport = getPatientFirstReport(patientId, Constant.ReportType.REPORT_FIRST.getType());
        if (firstReport == null) {
            throw new JeecgBootException("创建总结报告失败, 还没有首诊报告");
        }
        // endregion
        ReportSummary.SummaryReportContent content = new ReportSummary.SummaryReportContent();
        // region基本信息
        PatientBasicInfo basicInfo = getPatientBasicInfo(patientId);
        content.setBasicInfo(basicInfo);
        // endregion
        // region 服务方案
        ReportServiceProgramme serviceProgramme = getPatientServiceProgramme(patientId);
        Optional.ofNullable(serviceProgramme).ifPresent(content::setServiceProgramme);
        String startDate = null,endDate = null;
        if (serviceProgramme != null) {
            startDate = serviceProgramme.getServiceStartDate();
            Date endTime = DateUtils.getDate();
            endDate = DateUtils.compareYMD(serviceProgramme.getEndDate(),endTime)?DateUtil.formatDate(endTime):serviceProgramme.getServiceFinishDate();
        }else {
            return null;
        }
        // endregion
        // region 打卡率和达标率
//        SigninRateLine rate = getReportSummaryFinishedAndReachStandardRate(patientId);
//        content.setSigninAndReachStandardRate(rate);
        // endregion
        // region 打卡率和达标率(新)
        Date startDTemp = DateUtils.str2Date(startDate,DateUtils.date_sdf.get());
        Date endDTemp = DateUtils.str2Date(endDate, DateUtils.date_sdf.get());
        Map<Date, Integer> finishedRateMap = signinRecordService.getSigninFinishedRateMap(patientId, startDTemp, endDTemp);
//        Map<Date, Integer> reachStandardMap = uplowRecordService.getSugarReachStandard(patientId, startDTemp, endDTemp);
        Map<Integer, DtrdEntRdSigninTargetDetail> detailMap = getSigninTargetDetail(patientId, startDTemp, endDTemp);
        Map<Date, Integer> reachStandardMap = null;
        if(detailMap != null){
            reachStandardMap = uplowRecordService.getPeriodControllerTargetsReachRate(patientId, startDTemp, endDTemp, detailMap);
        }
        finishedRateMap = finishedRateMap==null?new HashMap<Date, Integer>():finishedRateMap;
        reachStandardMap = reachStandardMap==null?new HashMap<Date, Integer>():reachStandardMap;
        content.setSigninRateLine(ReportUtil.getFinishedAndReachStandardRate(startDTemp, endDTemp, finishedRateMap, reachStandardMap));
        // endregion
        // region 控制目标周期查询图表
        content.setControllerTargetReportList(signinTargetDetailService.getSummaryReportTarget(patientId, startDate, endDate));

        // endregion
        // region 日常监测趋势血糖模块（空腹与餐后血糖）
        int sourceType = 0; // 代表查询全部仪器的血糖
        SugarChart bloodSugarRecordsForCharts = sugarRecordService.getBloodSugarRecordsForCharts(patientId, startDate, endDate, sourceType);
        content.setSugarChart(bloodSugarRecordsForCharts);
        // endregion
        // region 日常监测趋势血压模块
        PeriodBloodPressure bloodPressureRecordsForCharts = bloodPressureRecordService.getBloodPressureRecordsForCharts(patientId, startDate, endDate);
        content.setPeriodBloodPressure(bloodPressureRecordsForCharts);
        // endregion
        // region 日常监测趋势体重模块 修改为从人体成分分析的数据中获得
//        PeriodBmi bmiDataForCharts = heightWeightRecordService.getBmiDataForCharts(patientId, startDate, endDate);
//        content.setPeriodBmi(bmiDataForCharts);
        content.setPeriodBmi(signinBodyService.getPeriodBmiSigninBody(patientId, startDate, endDate));
        // endregion
        // region 用药调整
        List<ReportDrugSuggest> drudSuggestList = suggestService.getDrudSuggestList(patientId);
        content.setDrugAdjust(drudSuggestList);
        // endregion
        // region 饮食得分
        PeriodFoodScore foodScoreForCharts = signinRecordSuggestService.getFoodScoreForCharts(patientId, startDate, endDate);
        Float dietScore = signinRecordSuggestService.getPatientSigninDietRecordScoreAvg(patientId, startDate, endDate);
        if( dietScore != null){
            if (foodScoreForCharts == null) {
                foodScoreForCharts = new PeriodFoodScore();
            }
            dietScore = (float)Math.round(dietScore*100)/100;
            foodScoreForCharts.setDietScore(dietScore);
        }
        content.setPeriodFoodScore(foodScoreForCharts);
        // endregion
        // region 患者档案
        // 服务前
        PatientArchive archiveFirst = firstReport.getPatientArchive();
        content.setArchiveFirst(archiveFirst);
        // 服务后
        PatientArchive archiveSummary = getReportPatientArchive(patientId, false, false, false, true);
        content.setArchiveSummary(archiveSummary);
        // endregion
        // region 打卡总结
        assert serviceProgramme != null;
        content.setSigninSummary(handleSummarySigninRecords(patientId, serviceProgramme.getStartDate(), serviceProgramme.getEndDate()));
        // endregion

        // region 控制目标 该方法已弃用，控制目标图表的生成已替换为setControllerTargetReportList
//        ReportTable table = targetDetailService.getReportWeekTargets(patientId, startDate, endDate);
//        content.setTargets(table);
        // endregion

        // region 量表评估
        // 首诊报告量表评估内容
        TotalEvaluationReports evaluationFirst = firstReport.getPatientEvaluation();
        content.setEvaluationFirst(evaluationFirst);
        // 总结报告量表评估内容
        TotalEvaluationReports evaluationSummary = evaluationService.getTotalEvaluationReports(patientId, new Date());
        content.setEvaluationSummary(evaluationSummary);
        // endregion
        // region 健康处方
//        ReportWeekSuggest suggest = getPatientSuggest(patientId);
//        content.setPrescription(suggest);
        reportSummary.setReportContent(content);
        // endregion
        // region 保存
        DtrdEntRdReport po = new DtrdEntRdReport();
        String packageName = packageService.getServingPackageName(patientId);
        if (packageName != null) {
            po.setReportName(packageName + Constant.ReportType.REPORT_SUMMARY.getName());
        } else {
            po.setReportName(Constant.ReportType.REPORT_SUMMARY.getName());
        }
        po.setReportType(Constant.ReportType.REPORT_SUMMARY.getType());
        po.setPatientId(patientId);
        po.setPatientArchive(JSONUtil.toJsonStr(content));
        po.setCreateBy(username);
        save(po);
        // endregion
        return reportSummary.parseFromPO(po);
    }

    private SigninRateLine getReportSummaryFinishedAndReachStandardRate(Integer patientId) {
        PatientSigninPlan signinPlan = signinPlanService.getSigninPlan(patientId);
        Date startDate = signinPlan.getSignInStartdate();
        Date endDate = signinPlan.getSignInEnddate();
        Map<Date, Integer> finishedRateMap = signinRecordService.getSigninFinishedRateMap(patientId, startDate, endDate);
        Map<Date, Integer> reachStandardMap = uplowRecordService.getSugarReachStandard(patientId, startDate, endDate);
        return ReportUtil.getFinishedAndReachStandardRate(startDate, endDate, finishedRateMap, reachStandardMap);
    }

    private PatientArchive getReportPatientArchive(Integer patientId, boolean basicInfo, boolean physical, boolean iconography, boolean lab) {
        // 患者档案
        PatientArchive archive = new PatientArchive();
        // 基本信息
        if (basicInfo) {
            PatientBasicInfo patientBasicInfo = getPatientBasicInfo(patientId);
            archive.setBasicInfo(patientBasicInfo);
        }
        // 生活方式报告
        LifewayReport lifeWayReport = lifewayService.getPatientLifeWayReport(patientId);
        archive.setLifewayReport(lifeWayReport);
        // 合并症
        DiabetesComorbidityReport comorbidityReport = comorbidityService.getPatientDiabetesComorbidityReport(patientId);
        archive.setComorbidityReport(comorbidityReport);
        // 并发症
        DiabetesComplicationReport complicationReport = complicationService.getPatientDiabetesComplicationReport(patientId);
        archive.setComplicationReport(complicationReport);
        // 糖尿病教育
        DiabetesEducationReport educationReport = educationService.getPatientDiabetesEducationReport(patientId);
        archive.setEducationReport(educationReport);
        // 糖尿病概述报告
        DiabetesOverviewReport overviewReport = overviewService.getPatientDiabetesOverviewReport(patientId);
        archive.setOverviewReport(overviewReport);
        // 既往病史
        AnamnesisReport anamnesisReport = anamnesisService.getPatientAnamnesisReport(patientId);
        archive.setAnamnesisReport(anamnesisReport);
        // 实验室检测
        LaboratoryReport laboratoryReport = laboratoryService.getPatientLaboratoryReport(patientId);
        if (!lab) {
            if(laboratoryReport != null){
                laboratoryReport = laboratoryReport.setNull();
            }
        }
        archive.setLaboratoryReport(laboratoryReport);
        // 影像学检测
        if (!iconography) {
            IconographyReport iconographyReport = iconographyService.getPatientIconographyReport(patientId);
            archive.setIconographyReport(iconographyReport);
        }
        // 体格检查
        if (!physical) {
            PhysicalReport physicalReport = physicalService.getPatientPhysicalReport(patientId);
            archive.setPhysicalReport(physicalReport);
        }
        return archive;
    }

    private ReportWeekSuggest getPatientSuggest(Integer patientId) {
        List<SigninSuggestBean> types = suggestService.getSuggestByPatientIdAndTypes(patientId,
                Constant.SuggestType.DIET.getType(),
                Constant.SuggestType.MEDICAL.getType(),
                Constant.SuggestType.SPORT.getType(),
                Constant.SuggestType.INSULIN.getType());
        ReportWeekSuggest suggest = null;
        if (CollectionUtil.isNotEmpty(types)) {
            suggest = new ReportWeekSuggest();
            for (SigninSuggestBean type : types) {
                Constant.SuggestType suggestType = Constant.SuggestType.valueOf(type.getSigninType());
                switch (suggestType) {
                    case INSULIN:
                        suggest.setInsulinSuggest(type.getSuggestContent());
                        String INSULINCreatTimeStr = DateUtils.dateformat(type.getRecordDate(), "yyyy-MM-dd");
                        suggest.setInsulinSuggestTime(DateUtils.str2Date(INSULINCreatTimeStr, DateUtils.date_sdf.get()));
                        suggest.setInsulinSuggestCreateBy(type.getCreateBy());
                        break;
                    case DIET:
                        suggest.setDietSuggest(type.getSuggestContent());
                        String DIETCreatTimeStr = DateUtils.dateformat(type.getRecordDate(), "yyyy-MM-dd");
                        suggest.setDietSuggestTime(DateUtils.str2Date(DIETCreatTimeStr, DateUtils.date_sdf.get()));
                        suggest.setDietSuggestCreateBy(type.getCreateBy());
                        break;
                    case SPORT:
                        suggest.setSportSuggest(type.getSuggestContent());
                        String SPORTCreatTimeStr = DateUtils.dateformat(type.getRecordDate(), "yyyy-MM-dd");
                        suggest.setSportSuggestTime(DateUtils.str2Date(SPORTCreatTimeStr, DateUtils.date_sdf.get()));
                        suggest.setSportSuggestCreateBy(type.getCreateBy());
                        break;
                    case MEDICAL:
                        suggest.setDrugSuggest(type.getSuggestContent());
                        String MEDICALCreatTimeStr = DateUtils.dateformat(type.getRecordDate(), "yyyy-MM-dd");
                        suggest.setDietSuggestTime(DateUtils.str2Date(MEDICALCreatTimeStr, DateUtils.date_sdf.get()));
                        suggest.setDietSuggestCreateBy(type.getCreateBy());
                }
            }
        }
        return suggest;
    }

    private ReportServiceProgramme getPatientServiceProgramme(Integer patientId) {
        DtrdEntRdArchiveReverseScheme scheme = reverseSchemeService.getByPatientId(patientId);
        ReportServiceProgramme serviceProgramme = null;
        if (scheme != null) {
            serviceProgramme = new ReportServiceProgramme();
            Integer packageId = scheme.getServiceTemplateId();
            if (packageId != null) {
                serviceProgramme.setServiceName(packageService.getPackageName(packageId));
                // 患者服务包关联Id如果没有删除这里是会有错误的。
                DtrdRlPackagePatient packageService = packagePatientRlService.getPackageService(patientId, packageId);
                if (packageService != null) {
                    Date startTime = packageService.getStartTime();
                    Date endTime = packageService.getEndTime();
                    serviceProgramme.setServicePeriod(DateUtils.combineTwoTime(startTime, endTime));
                    serviceProgramme.setServiceStartDate(DateUtil.formatDate(startTime));
                    serviceProgramme.setServiceFinishDate(DateUtil.formatDate(endTime));
                    serviceProgramme.setStartDate(startTime);
                    serviceProgramme.setEndDate(endTime);
                }
            }
            // 饮食 运动 用药计划 生活方式评估
            serviceProgramme = serviceProgramme.parseFromPO(scheme);
        }
        return serviceProgramme;
    }

    private PatientBasicInfo getPatientBasicInfo(Integer patientId) {
        DtrdEntRdPatient patient = patientService.getById(patientId);
        DtrdEntRdArchiveBasic basic = basicService.getOne(Wrappers.lambdaQuery(DtrdEntRdArchiveBasic.class)
                .eq(DtrdEntRdArchiveBasic::getPatientId, patientId));
        DtrdEntRdArchiveBasicFamily family = basicFamilyService.getOne(Wrappers.lambdaQuery(DtrdEntRdArchiveBasicFamily.class)
                .eq(DtrdEntRdArchiveBasicFamily::getPatientId, patientId)
                .last("limit 1"));
        DtrdEntRdArchivePhysical physical = physicalService.getByPatientId(patientId);
        PatientBasicInfo basicInfo = new PatientBasicInfo();
        // 家人
        Optional.ofNullable(family).ifPresent(basicInfo::parseFromPO);
        // 个人基本信息
        Optional.ofNullable(patient).ifPresent(p -> {
            Integer provinceId = p.getPatientsProvinceId();
            Integer cityId = p.getPatientsCityId();
            StringJoiner joiner = new StringJoiner("");
            if (provinceId != null) {
                String provinceName = districtInfoService.getDistrictNameByAreaId(provinceId);
                joiner.add(provinceName);
            }
            if (cityId != null && !cityId.equals(provinceId)) {
                String cityName = districtInfoService.getDistrictNameById(cityId);
                joiner.add(cityName);
            }
            basicInfo.setPatientsLocation(joiner.toString());
            basicInfo.parseFromPO(p);
        });
        // basic 表个人信息
        Optional.ofNullable(basic).ifPresent(basicInfo::parseFromPO);
        // 身高/体重/bmi
        Optional.ofNullable(physical).ifPresent(p -> {
            Float height = p.getHeight();
            Float weight = p.getWeight();
            if (height != null) {
                basicInfo.setHeight(height + "cm");
            }
            if (weight != null) {
                basicInfo.setWeight(weight + "kg");
            }
            Float bmi = p.getBmi() == null ? (height == null || weight == null) ? null : SchemeUtil.getBmi(height, weight) : p.getBmi();
            basicInfo.setBmi(bmi);
        });
        return basicInfo;
    }

    @SneakyThrows
    @Override
    public IPage<ReportListInfo> pageReport(ReportPageRequest request) {
        Integer type = request.getType();
        Integer patientId = request.getPatientId();
        LambdaQueryWrapper<DtrdEntRdReport> queryWrapper = baseQueryWrapper(patientId, type)
                .orderByDesc(DtrdEntRdReport::getCreateTime);
        String queryDate = request.getQueryDate();
        // 月报的时间查询
        if (StrUtil.isNotBlank(queryDate) && type.equals(Constant.ReportType.REPORT_MONTH.getType())) {
            DateTime start = DateUtil.parse(queryDate, "yyyy");
            DateTime end = DateUtil.offset(start, DateField.YEAR, 1);
            log.info("月报查询时间范围：{}, {}", start, end);
            queryWrapper.ge(DtrdEntRdReport::getCreateTime, start)
                    .lt(DtrdEntRdReport::getCreateTime, end);
        }
        // 周报的时间查询
        if (StrUtil.isNotBlank(queryDate) && type.equals(Constant.ReportType.REPORT_WEEK.getType())) {
            DateTime start = DateUtil.parse(queryDate, "yyyy-MM");
            DateTime end = DateUtil.offset(start, DateField.MONTH, 1);
            log.info("周报查询时间范围：{}, {}", start, end);
            queryWrapper.ge(DtrdEntRdReport::getCreateTime, start)
                    .lt(DtrdEntRdReport::getCreateTime, end);
        }
        IPage<DtrdEntRdReport> page = new Page<>(request.getPageNum(), request.getPageSize());
        page = page(page, queryWrapper);
        return page.convert(ReportListInfo::new);
    }

    @Override
    public ReportWeek getWeeklyReport(Integer dataId) {
        DtrdEntRdReport report = getById(dataId);
        if (report == null || !report.getReportType().equals(Constant.ReportType.REPORT_WEEK.getType())) {
            throw new JeecgBootException("获取报告失败");
        }
        ReportWeek reportWeek = new ReportWeek().parseFromPO(report);
        String name = userService.getRealNameByUserName(report.getPublisher());
        reportWeek.setCreator(name);
        return reportWeek;
    }

    @Override
    public ReportMonth getMonthReport(Integer dataId) {
        DtrdEntRdReport report = getById(dataId);
        if (report == null || !report.getReportType().equals(Constant.ReportType.REPORT_MONTH.getType())) {
            throw new JeecgBootException("获取报告失败");
        }
        ReportMonth reportMonth = new ReportMonth().parseFromPo(report);
        String name = userService.getRealNameByUserName(report.getPublisher());
        reportMonth.setCreator(name);
        return reportMonth;
    }

    @Override
    public List<Integer> getValidPatientIds() {
        return baseMapper.getValidPatientIds();
    }

    @Override
    public ReportFirst getPatientFirstReport(Integer patientId, Integer type) {
        LambdaQueryWrapper<DtrdEntRdReport> wrapper = Wrappers.lambdaQuery(DtrdEntRdReport.class)
                .eq(DtrdEntRdReport::getPatientId, patientId)
                .eq(DtrdEntRdReport::getReportType, type)
                .orderByDesc(DtrdEntRdReport::getCreateTime)
                .last("limit 1");
        DtrdEntRdReport report = getOne(wrapper);
        return Optional.ofNullable(report)
                .map(po -> {
                    ReportFirst reportFirst = new ReportFirst().parseFromPO(po);
                    String name = userService.getRealNameByUserName(po.getCreateBy());
                    reportFirst.setCreator(name);

                    if (reportFirst.getPatientArchive().getLaboratoryReport() != null) {

                        String[] dates = new String[]{"空腹", "30min", "1h", "2h", "3h"};
                        Map<String, String[]> sugarChart = new HashMap<>();
                        String[] values = new String[]{
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getSugarLimosisNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getSugar30minNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getSugar1hNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getSugar2hNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getSugar3hNo()),
                        };
                        sugarChart.put("date", dates);
                        sugarChart.put("value", values);
                        reportFirst.setSugarChart(sugarChart);

                        Map<String, String[]> ogttChart = new HashMap<>();
                        ogttChart.put("date", dates);
                        String[] ogttValues1 = new String[]{
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getIsletLimosisNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getIslet30minNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getIslet1hNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getIslet2hNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getIslet3hNo()),
                        };
                        String[] ogttValues2 = new String[]{
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getPeptideLimosisNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getPeptide30minNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getPeptide1hNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getPeptide2hNo()),
                                String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getPeptide3hNo()),
                        };
                        ogttChart.put("value1", ogttValues1);
                        ogttChart.put("value2", ogttValues2);
                        reportFirst.setOgttChart(ogttChart);
                    }

                    return reportFirst;
                })
                .orElse(null);
    }

    @Override
    public ReportSummary getPatientSummaryReport(Integer patientId) {
        LambdaQueryWrapper<DtrdEntRdReport> wrapper = baseQueryWrapperV2(patientId, Constant.ReportType.REPORT_SUMMARY.getType());
        DtrdEntRdReport report = getOne(wrapper);
        LambdaQueryWrapper<DtrdEntRdReport> wrapper1 = baseQueryWrapperV2(patientId, Constant.ReportType.REPORT_FIRST.getType());
        DtrdEntRdReport report1 = getOne(wrapper1);

        return Optional.ofNullable(report).map(p -> {
            ReportSummary reportSummary1 = Optional.ofNullable(report1).map(po -> {
                ReportSummary reportSummary = new ReportSummary().parseFromPO(p);
                ReportFirst reportFirst = new ReportFirst().parseFromPO(po);
                String name = userService.getRealNameByUserName(p.getCreateBy());
                reportFirst.setCreator(name);
                reportSummary.setCreator(name);

                String[] dates = new String[]{"空腹", "30min", "1h", "2h", "3h"};
                Map<String, String[]> ogttChartFirst = new HashMap<>();
                Map<String, String[]> ogttChartSummary = new HashMap<>();
                ogttChartFirst.put("date", dates);
                ogttChartSummary.put("date", dates);

                if (reportFirst.getPatientArchive().getLaboratoryReport() != null) {
                    String[] ogttValues1 = new String[]{
                            String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getIsletLimosisNo()),
                            String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getIslet30minNo()),
                            String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getIslet1hNo()),
                            String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getIslet2hNo()),
                            String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getIslet3hNo()),
                    };
                    String[] ogttValues2 = new String[]{
                            String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getPeptideLimosisNo()),
                            String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getPeptide30minNo()),
                            String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getPeptide1hNo()),
                            String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getPeptide2hNo()),
                            String.valueOf(reportFirst.getPatientArchive().getLaboratoryReport().getPeptide3hNo()),
                    };
                    ogttChartFirst.put("value1", ogttValues1);
                    ogttChartFirst.put("value2", ogttValues2);
                }
                reportSummary.setOgttChartFirst(ogttChartFirst);

                if (getReportPatientArchive(patientId, false, true, true, true).getLaboratoryReport() != null) {
                    String[] ogttValues3 = new String[]{
                            String.valueOf(getReportPatientArchive(patientId, false, true, true, true).getLaboratoryReport().getIslet1hNo()),
                            String.valueOf(getReportPatientArchive(patientId, false, true, true, true).getLaboratoryReport().getIslet30minNo()),
                            String.valueOf(getReportPatientArchive(patientId, false, true, true, true).getLaboratoryReport().getIslet1hNo()),
                            String.valueOf(getReportPatientArchive(patientId, false, true, true, true).getLaboratoryReport().getIslet2hNo()),
                            String.valueOf(getReportPatientArchive(patientId, false, true, true, true).getLaboratoryReport().getIslet3hNo()),
                    };
                    String[] ogttValues4 = new String[]{
                            String.valueOf(getReportPatientArchive(patientId, false, true, true, true).getLaboratoryReport().getPeptideLimosisNo()),
                            String.valueOf(getReportPatientArchive(patientId, false, true, true, true).getLaboratoryReport().getPeptide30minNo()),
                            String.valueOf(getReportPatientArchive(patientId, false, true, true, true).getLaboratoryReport().getPeptide1hNo()),
                            String.valueOf(getReportPatientArchive(patientId, false, true, true, true).getLaboratoryReport().getPeptide2hNo()),
                            String.valueOf(getReportPatientArchive(patientId, false, true, true, true).getLaboratoryReport().getPeptide3hNo()),
                    };
                    ogttChartSummary.put("value3", ogttValues3);
                    ogttChartSummary.put("value4", ogttValues4);
                }
                reportSummary.setOgttchartSummary(ogttChartSummary);

                return reportSummary;
            }).orElse(null);
            return reportSummary1;
        }).orElse(null);
    }

    @Override
    public boolean removeReport(Integer dataId) {
        return removeById(dataId);
    }

    @Override
    public PatientReportIndex getPatientReportIndex(Integer patientId, Date queryDateWeek, Date queryDateMonth) {
        PatientReportIndex reportIndex = new PatientReportIndex(patientId);
        // 首诊报告内容
        LambdaQueryWrapper<DtrdEntRdReport> wrapper1 = baseQueryWrapper(patientId, Constant.ReportType.REPORT_FIRST.getType());
        DtrdEntRdReport first = getOne(wrapper1);
        if (first != null) {
            reportIndex.setReportFirst(new ReportListInfo(first));
        }
        // 总结报告内容
        LambdaQueryWrapper<DtrdEntRdReport> wrapper2 = baseQueryWrapper(patientId, Constant.ReportType.REPORT_SUMMARY.getType());
        DtrdEntRdReport summary = getOne(wrapper2);
        if (summary != null) {
            reportIndex.setReportSummary(new ReportListInfo(summary));
        }
        // 周报
        LambdaQueryWrapper<DtrdEntRdReport> wrapper3 = baseQueryWrapper(patientId, Constant.ReportType.REPORT_WEEK.getType());
        String queryDateWeekStr = DateUtil.format(queryDateWeek, "yyyy-MM");
        DateTime weekStartTime = DateUtil.parse(queryDateWeekStr, "yyyy-MM");
        DateTime weekEndTime = DateUtil.offset(weekStartTime, DateField.MONTH, 1);
        wrapper3.ge(DtrdEntRdReport::getCreateTime, weekStartTime)
                .lt(DtrdEntRdReport::getCreateTime, weekEndTime);
        List<DtrdEntRdReport> weekReports = list(wrapper3);
        if (CollectionUtil.isNotEmpty(weekReports)) {
            List<ReportListInfo> collect = weekReports.stream().map(ReportListInfo::new).collect(Collectors.toList());
            reportIndex.setReportWeek(collect);
        }
        // 月报
        LambdaQueryWrapper<DtrdEntRdReport> wrapper4 = baseQueryWrapper(patientId, Constant.ReportType.REPORT_MONTH.getType());
        String queryDateMonthStr = DateUtil.format(queryDateWeek, "yyyy");
        DateTime monthStartTime = DateUtil.parse(queryDateMonthStr, "yyyy");
        DateTime monthEndTime = DateUtil.offset(monthStartTime, DateField.YEAR, 1);
        wrapper4.ge(DtrdEntRdReport::getCreateTime, monthStartTime)
                .lt(DtrdEntRdReport::getCreateTime, monthEndTime);
        List<DtrdEntRdReport> monthReports = list(wrapper4);
        if (CollectionUtil.isNotEmpty(monthReports)) {
            List<ReportListInfo> collect = monthReports.stream().map(ReportListInfo::new).collect(Collectors.toList());
            reportIndex.setReportMonth(collect);
        }
        return reportIndex;
    }

    @Override
    public boolean updateReportContent(ReportSummaryUpdateRequest request, String name) {
        Integer reportId = request.getReportId();
        DtrdEntRdReport report = getById(reportId);
        if (report == null || !report.getReportType().equals(Constant.ReportType.REPORT_SUMMARY.getType())) {
            return false;
        }
        Integer patientId = report.getPatientId();
        ReportSummary.SummaryReportContent summaryReportContent = JSONUtil.toBean(report.getPatientArchive(), ReportSummary.SummaryReportContent.class);
        PatientArchive archiveSummary = summaryReportContent.getArchiveSummary();
        if (archiveSummary != null) {
            Integer type = request.getArchiveType();
            if (type != null) {
                Constant.UpdateSummaryReportType updateSummaryReportType = Constant.UpdateSummaryReportType.valueOf(type);
                switch (updateSummaryReportType) {
                    case PHYSICAL:
                        PhysicalReport physicalReport = physicalService.getPatientPhysicalReport(patientId);
                        archiveSummary.setPhysicalReport(physicalReport);
                        break;
                    case LAB:
                        LaboratoryReport laboratoryReport = laboratoryService.getPatientLaboratoryReport(patientId);
                        archiveSummary.setLaboratoryReport(laboratoryReport);
                        break;
                    case ICONOGRAPHY:
                        IconographyReport iconographyReport = iconographyService.getPatientIconographyReport(patientId);
                        archiveSummary.setIconographyReport(iconographyReport);
                        break;
                }
            }
        }
        String updateContent = JSONUtil.toJsonStr(summaryReportContent);
        report.setPatientArchive(updateContent);
        report.setPublishStatus(request.getStatus());
        report.setSummary(request.getSummary());
        report.setPublisher(name);
        return updateById(report);
    }

    @Override
    public boolean updateFirstReportContent(ReportFirstUpdateRequest request, String name) {
        Integer reportId = request.getReportId();
        DtrdEntRdReport report = getById(reportId);
        if (report == null) {
            return false;
        }
//      统一修改，报告单读出来的统一存放在报告单字段里，新增的图片统一在updateRequest下。
        report.setFirstEvaluate(JSONUtil.toJsonStr(request.makeJson()));
//        if (request.getReportPictures() != null) {
//            report.setPatientArchiveReport(request.getReportPictures());
//        }
        // region 保存报告图片
        if(StrUtil.isNotBlank(request.getReportPictures())){
            saveOrUpdateArchiveReport(request.getReportPictures(), report.getPatientId());
        }
        // endregion 保存报告图片
        report.setPublisher(name);
        report.setPublishStatus(Constant.ReportPublishType.valueOf(request.getPublishStatus()).getType());
        if (request.getPublishStatus() == Constant.ReportPublishType.HAD_PUBLISHED.getType()) {
            report.setPublishTime(new Date());
        } else {
            report.setPublishTime(null);
        }
        return updateById(report);
    }

    private void saveOrUpdateArchiveReport(String reportPictures, Integer patientId){
        List<DtrdEntRdArchiveReport> list = new ArrayList<>();
        String[] photos = reportPictures.split(",");
        for(String str: photos){
            if(StrUtil.isBlank(str)){
                continue;
            }
            DtrdEntRdArchiveReport archiveReport = new DtrdEntRdArchiveReport();
            archiveReport.setReportType(0); // 未分组
            archiveReport.setPatientId(patientId);
            archiveReport.setReportUrls(str);
            archiveReport.setCreateTime(DateUtils.getDateYMD());
            archiveReport.setIsDel(0);
            list.add(archiveReport);
        }
        archiveReportService.saveOrUpdateBatch(list);
    }

    @Override
    public boolean updateWeekReportContent(ReportWeekUpdateRequest request, String name) {
        Integer reportId = request.getReportId();
        DtrdEntRdReport report = getById(reportId);
        if (report == null) {
            return false;
        }
        report.setPatientArchiveReport(JSONUtil.toJsonStr(new ReportWeekUpdateRequest.ReportWeekInputUpdate().makeJson(request)));
        // region 保存报告图片
        if(StrUtil.isNotBlank(request.getReportPictures())){
            saveOrUpdateArchiveReport(request.getReportPictures(), report.getPatientId());
        }
        // endregion 保存报告图片
        report.setPublisher(name);
        report.setSummary(request.getSummary());
        report.setPublishStatus(Constant.ReportPublishType.valueOf(request.getPublishStatus()).getType());
        if (request.getPublishStatus() == Constant.ReportPublishType.HAD_PUBLISHED.getType()) {
            report.setPublishTime(new Date());
        } else {
            report.setPublishTime(null);
        }
        return updateById(report);
    }

    @Override
    public boolean updateMonthReportContent(ReportMonthUpdateRequest request, String name) {
        Integer reportId = request.getReportId();
        DtrdEntRdReport report = getById(reportId);
        if (report == null) {
            return false;
        }
        // region 读取控制目标，将控制目标的数据进行更新
        ReportMonth.MonthReportContent content = JSONUtil.toBean(report.getPatientArchive(), ReportMonth.MonthReportContent.class);
        if (content != null ){
            List<ControllerTargetReport> targetReportList = content.getControllerTargetReportList();
            targetReportList = handleTargetReport(request.getLaboratoryList(), targetReportList, reportId, report.getPatientId());
            content.setControllerTargetReportList(targetReportList);
        }
        report.setPatientArchive(JSONUtil.toJsonStr(content));
        // endregion 读取控制目标，将控制目标的数据进行更新
        report.setPatientArchiveReport(JSONUtil.toJsonStr(new ReportMonthUpdateRequest.ReportMonthInputUpdate().makeJson(request)));
        // region 保存报告图片
        if(StrUtil.isNotBlank(request.getReportPictures())){
            saveOrUpdateArchiveReport(request.getReportPictures(), report.getPatientId());
        }
        // endregion 保存报告图片
        report.setPublisher(name);
        report.setSummary(request.getSummary());
        report.setPublishStatus(Constant.ReportPublishType.valueOf(request.getPublishStatus()).getType());
        if (request.getPublishStatus() == Constant.ReportPublishType.HAD_PUBLISHED.getType()) {
            report.setPublishTime(new Date());
        } else {
            report.setPublishTime(null);
        }
        return updateById(report);
    }

    /**
     * 本周期减去上一周期
     * @param laboratoryMap
     * @param targetReportList
     * @param reportId
     * @param patientId
     * @return
     */
    private List<ControllerTargetReport> handleTargetReport(Map<Integer, Float> laboratoryMap, List<ControllerTargetReport> targetReportList, Integer reportId, Integer patientId){
        if(CollectionUtil.isEmpty(targetReportList)){
            return null;
        }
        if(CollectionUtil.isEmpty(laboratoryMap)){
            return targetReportList;
        }
        List<DtrdEntRdReportTarget> reportTargets = new ArrayList<>();
        for(ControllerTargetReport targetReport: targetReportList){
            DtrdEntRdReportTarget reportTarget = new DtrdEntRdReportTarget();
            Integer typeId = targetReport.getTypeId();
            Constant.LABORATORY laboratory = Constant.LABORATORY.valueOf(typeId);
            Float value = laboratoryMap.get(typeId);
            if(value == null){
                continue;
            }
            // region 保存控制目标的输入
            reportTarget.setReportId(reportId);
            reportTarget.setTypeId(typeId);
            reportTarget.setRecordDate(DateUtil.offset(DateUtil.beginOfMonth(DateUtils.getDate()), DateField.DAY_OF_MONTH, -1));
            reportTarget.setRecordValue(value);
            reportTarget.setPatientId(patientId);
            reportTargets.add(reportTarget);

            // endregion 保存控制目标的输入
            // 如果初始值为空的话，直接将该值设置为初始值
            if (targetReport.getStartValue() == null) {
                targetReport.setStartValue(value);
            }
            targetReport.setThisPeriodValue(value);
            Float trendValue = 0F;
            if(targetReport.getLastPeriodValue() != null){
                trendValue = (float)Math.round((value - targetReport.getLastPeriodValue())*100)/100;
            }
            targetReport.setTrendValue(trendValue);
            if(trendValue == 0){
                targetReport.setTrend(2);
            }else {
                targetReport.setTrend(trendValue>0?laboratory.getHigh():laboratory.getLow());
            }
        }
        reportTargetService.saveBatch(reportTargets);
        return targetReportList;
    }

    @Override
    public boolean updateSummaryReportContent(ReportSummaryUpdateRequest request, String name) {
        Integer reportId = request.getReportId();
        DtrdEntRdReport report = getById(reportId);
        if (report == null || !report.getReportType().equals(Constant.ReportType.REPORT_SUMMARY.getType())) {
            return false;
        }
        Integer patientId = report.getPatientId();
        ReportSummary.SummaryReportContent summaryReportContent = JSONUtil.toBean(report.getPatientArchive(), ReportSummary.SummaryReportContent.class);
        PatientArchive archiveSummary = summaryReportContent.getArchiveSummary();
        // region 读取控制目标，将控制目标的数据进行更新
        List<ControllerTargetReport> targetReportList = summaryReportContent.getControllerTargetReportList();
        targetReportList = handleSummaryTargetReport(request.getLaboratoryMap(), targetReportList, reportId, report.getPatientId());
        summaryReportContent.setControllerTargetReportList(targetReportList);
        // endregion 读取控制目标，将控制目标的数据进行更新
        if (archiveSummary != null) {
            Integer type = request.getArchiveType();
            if (type != null) {
                Constant.UpdateSummaryReportType updateSummaryReportType = Constant.UpdateSummaryReportType.valueOf(type);
                switch (updateSummaryReportType) {
                    case PHYSICAL:
                        PhysicalReport physicalReport = physicalService.getPatientPhysicalReport(patientId);
                        archiveSummary.setPhysicalReport(physicalReport);
                        break;
                    case LAB:
                        LaboratoryReport laboratoryReport = laboratoryService.getPatientLaboratoryReport(patientId);
                        archiveSummary.setLaboratoryReport(laboratoryReport);
                        break;
                    case ICONOGRAPHY:
                        IconographyReport iconographyReport = iconographyService.getPatientIconographyReport(patientId);
                        archiveSummary.setIconographyReport(iconographyReport);
                        break;
                }
            }
        }
        String updateContent = JSONUtil.toJsonStr(summaryReportContent);
        report.setPatientArchive(updateContent);
        report.setPatientArchiveReport(JSONUtil.toJsonStr(new ReportSummaryUpdateRequest.ReportSummaryInputUpdate().makeJson(request)));
        // region 保存报告图片
        if(StrUtil.isNotBlank(request.getReportPictures())){
            saveOrUpdateArchiveReport(request.getReportPictures(), report.getPatientId());
        }
        // endregion 保存报告图片
        report.setPublisher(name);
        report.setSummary(request.getSummary());
        report.setPublishStatus(Constant.ReportPublishType.valueOf(request.getStatus()).getType());
        if (request.getStatus() == Constant.ReportPublishType.HAD_PUBLISHED.getType()) {
            report.setPublishTime(new Date());
        } else {
            report.setPublishTime(null);
        }
        return updateById(report);
    }

    /**
     * 计算总结报告的控制目标，当前输入值减去初始值
     * @param laboratoryMap
     * @param targetReportList
     * @param reportId
     * @param patientId
     * @return
     */
    private List<ControllerTargetReport> handleSummaryTargetReport(Map<Integer, Float> laboratoryMap, List<ControllerTargetReport> targetReportList, Integer reportId, Integer patientId) {
        if(CollectionUtil.isEmpty(targetReportList)){
            return null;
        }
        if(CollectionUtil.isEmpty(laboratoryMap)){
            return targetReportList;
        }
//        List<DtrdEntRdReportTarget> reportTargets = new ArrayList<>();
        for(ControllerTargetReport targetReport: targetReportList){
            DtrdEntRdReportTarget reportTarget = new DtrdEntRdReportTarget();
            Integer typeId = targetReport.getTypeId();
            Constant.LABORATORY laboratory = Constant.LABORATORY.valueOf(typeId);
            Float value = laboratoryMap.get(typeId);
            if(value == null){
                continue;
            }
            // region 保存控制目标的输入
//            reportTarget.setReportId(reportId);
//            reportTarget.setTypeId(typeId);
//            reportTarget.setRecordDate(DateUtils.getDate());
//            reportTarget.setRecordValue(value);
//            reportTarget.setPatientId(patientId);
//            reportTargets.add(reportTarget);

            // endregion 保存控制目标的输入
            // 如果初始值为空的话，直接将该值设置为初始值
            if (targetReport.getStartValue() == null) {
                targetReport.setStartValue(value);
            }
            targetReport.setThisPeriodValue(value);
            Float trendValue = (float)Math.round((value - targetReport.getStartValue())*100)/100;
            targetReport.setTrendValue(trendValue);
            if(trendValue == 0){
                targetReport.setTrend(2);
            }else {
                targetReport.setTrend(trendValue>0?laboratory.getHigh():laboratory.getLow());
            }
        }
//        reportTargetService.saveBatch(reportTargets);
        return targetReportList;
    }

    private LambdaQueryWrapper<DtrdEntRdReport> baseQueryWrapper(Integer patientId, Integer reportType) {
        return Wrappers.lambdaQuery(DtrdEntRdReport.class)
                .eq(DtrdEntRdReport::getPatientId, patientId)
                .eq(DtrdEntRdReport::getReportType, reportType)
                .eq(DtrdEntRdReport::getIsDel, 0);
    }

    private LambdaQueryWrapper<DtrdEntRdReport> baseQueryWrapperV2(Integer patientId, Integer reportType) {
        return Wrappers.lambdaQuery(DtrdEntRdReport.class)
                .eq(DtrdEntRdReport::getPatientId, patientId)
                .eq(DtrdEntRdReport::getReportType, reportType)
                .eq(DtrdEntRdReport::getIsDel, 0)
                .orderByDesc(DtrdEntRdReport::getCreateTime)
                .last("limit 1");
    }

    private LambdaUpdateWrapper<DtrdEntRdReport> baseUpdateWrapper(Integer patientId, Integer reportType) {
        return Wrappers.lambdaUpdate(DtrdEntRdReport.class)
                        .eq(DtrdEntRdReport::getIsDel, 0);
    }
}
